//
//  NSString+JRMFEncrypt.m
//  JRMFMobileVerify
//
//  Created by Criss on 2017/12/26.
//  Copyright © 2017年 SONG. All rights reserved.
//

#import "NSString+JRMFEncrypt.h"

@implementation NSString (JRMFEncrypt)


/**
 des + base64 加密

 @param key 密钥
 @return 加密后的字符串
 */
- (NSString *)threeDesAndBase64EncryWithKey:(NSString *)key
{
    return [self threeDesAndBase64EncOrDec:kCCEncrypt key:key];
}


/**
 des + base64 解密

 @param key 密钥
 @return 解密后字符串
 */
- (NSString *)threeDesAndBase64DecryptWithKey:(NSString *)key
{
    return [self threeDesAndBase64EncOrDec:kCCDecrypt key:key];
}

- (NSString*)threeDesAndBase64EncOrDec:(CCOperation)encryptOrDecrypt key:(NSString *)keyInput {
    
    const void *vplainText;
    size_t plainTextBufferSize;
    NSString *keyStr = [[[keyInput md5String] substringWithRange:NSMakeRange(0, 24)] lowercaseString];
    NSData *decodedKey = [keyStr dataUsingEncoding:NSUTF8StringEncoding];
    if (encryptOrDecrypt == kCCDecrypt) {
        NSData *EncryptData = [[NSData alloc] initWithBase64EncodedString:self options:0];
        plainTextBufferSize = [EncryptData length];
        vplainText = [EncryptData bytes];
    } else {
        NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
        int redu = data.length % 8;
        if (redu > 0) {
            NSMutableString *newText = [[NSMutableString alloc] initWithString:self];
            for (int i=0; i< 8 - redu; i++) {
                [newText appendString:@" "];
            }
            data = [newText dataUsingEncoding:NSUTF8StringEncoding];
        }
        plainTextBufferSize = [data length];
        vplainText = (const void *) [data bytes];
    }
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    unsigned char result1[24];
    memcpy(result1, decodedKey.bytes, decodedKey.length);
    
    uint8_t iv[kCCBlockSize3DES];
    memset((void *) iv, 0x30, (size_t) sizeof(iv));
    
    ccStatus = CCCrypt(encryptOrDecrypt,
                       kCCAlgorithm3DES,
                       0,
                       result1,//key
                       kCCKeySize3DES,
                       iv ,  //iv,
                       vplainText,  //plainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    if (ccStatus != kCCSuccess) {
        if (ccStatus == kCCParamError)  NSLog(@"PARAM ERROR");
        else if (ccStatus == kCCBufferTooSmall) NSLog(@"BUFFER TOO SMALL");
        else if (ccStatus == kCCMemoryFailure) NSLog(@"MEMORY FAILURE");
        else if (ccStatus == kCCAlignmentError) NSLog(@"ALIGNMENT");
        else if (ccStatus == kCCDecodeError) NSLog(@"DECODE ERROR");
        else if (ccStatus == kCCUnimplemented) NSLog(@"UNIMPLEMENTED");
        return nil;
    }
    NSString *result;
    if (encryptOrDecrypt == kCCDecrypt) {
        result = [ [NSString alloc] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding];
        result = [result stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        result = [result stringByRemovingPercentEncoding];
    } else {
        NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        NSString *myStr = [myData base64EncodedStringWithOptions:0];
        myStr = [myStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        result = [myStr stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    }
    return result;
}

/**
 des 加密

 @param key 密钥
 @return 加密后字符串
 */
- (NSString *)desEncryWithKey:(NSString *)key
{
    //*加密1.字符串转data
    NSData * baseData = [self dataUsingEncoding:NSUTF8StringEncoding];
    
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    NSUInteger dataLength = [baseData length];
    
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus;
    cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                          keyPtr, kCCBlockSizeDES,
                          NULL,
                          [baseData bytes], dataLength,
                          buffer, bufferSize,
                          &numBytesEncrypted);
    //    if (cryptStatus == kCCSuccess) {
    NSData * data = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    //    }
    
    //    free(buffer);
    
    //*加密2.data转byte
    Byte *jmbytes = (Byte *)[data bytes];
    
    
    //*加密3.下面是Byte 转换为16进制。
    NSString *hexString = @"";
    for(int i=0;i<[data length];i++) {
        NSString *newHexStr = [NSString stringWithFormat:@"%X",jmbytes[i]&0xff];///16进制数
        if([newHexStr length]==1)
            hexString = [NSString stringWithFormat:@"%@0%@",hexString,newHexStr];
        else
            hexString = [NSString stringWithFormat:@"%@%@",hexString,newHexStr];
    }
    
    return hexString;
}


/**
 des 解密

 @param key key
 @return 解密后字符串
 */
- (NSString*)desDecryptWithKey:(NSString*)key
{
    NSString * basejmString = [NSString stringWithFormat:@"%@", self.lowercaseString];
    //*解密1.十六进制转byte
    int j=0;
    int tmpLength = (int)[basejmString length]/2;
    Byte bytes[tmpLength];  ///3ds key的Byte 数组， 128位
    //    NSLog(@"tmpLength = %d", tmpLength);
    for(int i=0; i<[basejmString length]; i++) {
        int int_ch;  /// 两位16进制数转化后的10进制数
        unichar hex_char1 = [basejmString characterAtIndex:i]; ////两位16进制数中的第一位(高位*16)
        int int_ch1;
        if(hex_char1 >= '0' && hex_char1 <='9')
            int_ch1 = (hex_char1-48)*16;   //// 0 的Ascll - 48
        else if(hex_char1 >= 'A' && hex_char1 <='F')
            int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
        else
            int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97
        i++;
        
        unichar hex_char2 = [basejmString characterAtIndex:i]; ///两位16进制数中的第二位(低位)
        int int_ch2;
        if(hex_char2 >= '0' && hex_char2 <='9')
            int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
        else if(hex_char1 >= 'A' && hex_char1 <='F')
            int_ch2 = hex_char2-55; //// A 的Ascll - 65
        else
            int_ch2 = hex_char2-87; //// a 的Ascll - 97
        
        int_ch = int_ch1+int_ch2;
        //        NSLog(@"int_ch=%d",int_ch);
        bytes[j] = int_ch;  ///将转化后的数放入Byte数组里
        j++;
    }
    
    //*解密2.byte转data
    NSData *newData = [[NSData alloc] initWithBytes:bytes length:tmpLength];
    //    NSLog(@"newData=%@",newData);
    
    //解密3.data经过DEC解密
    //    NSData * jmdata;
    char keyPtr[kCCKeySizeAES256+1];
    bzero(keyPtr, sizeof(keyPtr));
    
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    NSUInteger dataLength = [newData length];
    
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus;
    cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES,
                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                          keyPtr, kCCBlockSizeDES,
                          NULL,
                          [newData bytes], dataLength,
                          buffer, bufferSize,
                          &numBytesDecrypted);
    
    //    if (cryptStatus == kCCSuccess) {
    NSData * jmdata = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    //    }
    
    //    free(buffer);
    
    NSString * jm_str = [[NSString alloc] initWithData:jmdata encoding:NSUTF8StringEncoding];
    
    return jm_str;
}


/**
 base 64 编码

 @return <#return value description#>
 */
- (NSString *)base64EncodedString
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
    return [data base64EncodedStringWithOptions:0];
}

/**
 base 64 解码
 
 @return <#return value description#>
 */
- (NSString *)base64DecodedString
{
    NSData *data = [[NSData alloc]initWithBase64EncodedString:self options:0];
    return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}

/**
 字符串转 16进制
 @return <#return value description#>
 */
- (NSString *)hexString
{
    NSData * data = [self dataUsingEncoding:NSUTF8StringEncoding];
    Byte *jmbytes = (Byte *)[data bytes];
    NSString *hexString = @"";
    for(int i=0;i<[data length];i++) {
        NSString *newHexStr = [NSString stringWithFormat:@"%X",jmbytes[i]&0xff];///16进制数
        if([newHexStr length]==1)
            hexString = [NSString stringWithFormat:@"%@0%@",hexString,newHexStr];
        else
            hexString = [NSString stringWithFormat:@"%@%@",hexString,newHexStr];
    }
    return hexString;
}


/**
 MD5 加密 32位

 @return <#return value description#>
 */
- (NSString *)md5String{
    const char *cStr = [self UTF8String];
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    
    CC_MD5(cStr, (CC_LONG)strlen(cStr), digest);
    
    NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [result appendFormat:@"%02X", digest[i]];
    }
    
    return result;
}

@end
